package org.wattdepot.cli.commands;

import java.util.List;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.util.tstamp.Tstamp;


/**
 * This class contains a command that prints out the carbon content that
 * is emitted by a source for the hour at the specified time stamp, assuming
 * a constant rate of emitted carbon and energy generated. 
 * It uses a sampling interval to calculate this number.
 * 
 * @author David Mau
 */
public class CarbonContentCommand implements WattDepotCliCommand {
  //Default client-server connection to use unless given one.
  private WattDepotClient client = new WattDepotClient(debug);

  /**
   * This constructor makes sure that the client really is connected to the server.
   * 
   * @param anotherClient Specifies if the user wants to use another WattDepot server
   * other than the default simulation one.
   */
  public CarbonContentCommand( String anotherClient ) {
    // If another client is provided
    if ( anotherClient != null ) {
      client = new WattDepotClient( anotherClient );
    }
    
    // Stop right away if we cannot contact server.
    if (!client.isHealthy()) {
      System.out.println("Failed to connect to " + client.getWattDepotUri());
      return;
    }
    // Indicate successful connection.
    //System.out.println("Connected to " + client.getWattDepotUri());
  }
  
  /**
   * This method returns a double that reflects how much power is generated or consumed by a source
   * at a given time stamp.
   * 
   * Created by David Mau.
   * 
   * @param args A list of arguments given to this command.
   * @return A String in MegaWatts of how much carbon or energy was generated.
   */
  public String doCommand( List<String> args) {
    String output = "";
    
    // Check to see if the right amount of arguments was given.
    if ( args.size() > 3 ) {
      output = tooManyArguments;
      output = output.concat( cr );
      return output;
    }
    if ( args.size() < 3 ) {
      output = missingArguments;
      output = output.concat( cr );
      return output;
    }
    
    // Get data from the arguments.
    String source = args.get( 0 );
    String time = args.get( 1 );
    String minutes = args.get( 2 );
    
    // Convert the time stamp String into two XML ones.
    // First, the start time.
    XMLGregorianCalendar xmlTimeStart = null;
    try {
      xmlTimeStart = Tstamp.makeTimestamp(time);
    }
    catch (Exception e) {
      output = badTimeStamp;
      output = output.concat(e.toString());
      output = output.concat(cr);
      return output;
    }
    
    // Now convert the end time.
    // Copy the start time.
    XMLGregorianCalendar xmlTimeEnd = xmlTimeStart;
    // Increment by an hour.
    xmlTimeEnd = Tstamp.incrementHours(xmlTimeEnd, 1);
    
    int interval = 0;
    // Attempt to turn the minutes String into an integer.
    try {
      interval = Integer.valueOf(minutes);
    }
    catch (NumberFormatException e) {
      output = intervalNotNumber;
      output = output.concat(e.toString());
      output = output.concat(cr);
      return output;
    }

    // If the converted integer is negative or zero, return an error.
    if (interval <= 0) {
      output = intervalNegativeOrZero;
      output = output.concat(cr);
      return output;
    }
    
    double energyOutput = 0.0;
    double carbonOutput = 0.0;
    // Attempt to collect data from the client about the carbon and energy.
    try {
      energyOutput = client.getEnergyGenerated(source, xmlTimeStart, 
          xmlTimeEnd, interval);
      carbonOutput = client.getCarbonEmitted(source, xmlTimeStart, 
          xmlTimeEnd, interval);
    }
    catch (NotAuthorizedException e) {
      output = notAuthorized;
      output = output.concat(e.toString());
      output = output.concat(cr);
      return output;
    }
    catch (ResourceNotFoundException e) {
      output = resourceNotFound;
      output = output.concat(e.toString());
      output = output.concat(cr);
      return output;
    }
    catch (BadXmlException e) {
      output = badXml;
      output = output.concat(e.toString());
      output = output.concat(cr);
      return output;
    }
    catch (MiscClientException e) {
      output = miscClient;
      output = output.concat(e.toString());
      output = output.concat(cr);
      return output;
    }
    
    // The energy output is in Watt-Hours
    // Convert to MegaWatt-Hours.
    energyOutput = energyOutput / 1000000;
    
    // Now divide carbon by energy.
    double doubleOutput = carbonOutput / energyOutput;
    
    // Convert from double to String
    output = Double.toString( doubleOutput );
    output = output.concat( " pounds CO2/MegaWatt-Hours" );
    output = output.concat(cr);
    
    return output;
  }
}
